package com.fox.stock.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fox.stock.constant.StockConstant;
import com.fox.stock.pojo.vo.resq.R;
import com.fox.stock.pojo.vo.resq.ResponseCode;
import com.fox.stock.security.util.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class JwtAuthorizationFilter extends OncePerRequestFilter {

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String requestURI = request.getRequestURI();
        // 复用 SecurityConfig 中的公共路径配置逻辑
        String[] pubPaths = {"/**/*.css", "/**/*.js", "/favicon.ico", "/doc.html",
                "/druid/**", "/webjars/**", "/v2/api-docs", "/api/captcha",
                "/swagger/**", "/swagger-resources/**", "/swagger-ui.html"};

        AntPathMatcher pathMatcher = new AntPathMatcher();
        for (String pattern : pubPaths) {
            if (pathMatcher.match(pattern, requestURI)) {
                return true; // 不对此路径应用过滤器
            }
        }
        return false;
    }

    /*授权过滤器*/
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        // 获取reques对象下的token数据
        String token = request.getHeader(StockConstant.TOKEN_HEADER);
        // 判断token字符串是否存在
        if (token == null){
            // 不存在说明还未登录,放行执行登录操作
            filterChain.doFilter(request,response);
            return;
        }
        // token不为空说明有登录过,再判断token是否合法有效
        // 解析token字符串
        Claims claims = JwtTokenUtil.checkJWT(token);
        // 判断token是否过期
        if (claims == null){
            // 过期 提醒用户重新登录
            R<Object> error = R.error(ResponseCode.INVALID_TOKEN);
            response.getWriter().write(new ObjectMapper().writeValueAsString(error));
            return;
        }
        // token合法
        // 获取用户信息并组装认证成功的票据对象
        String username = JwtTokenUtil.getUsername(token);
        String userRole = JwtTokenUtil.getUserRole(token);
        // 生成权限集合对象
        userRole = StringUtils.strip(userRole,"[]");
        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(userRole);
        // 将用户名和权限集合封装到UsernamePasswordAuthenticationToken对象中
        UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken(username, null, authorities);
        // 将user放入安全上下文中,以给后续验证资源
        SecurityContextHolder.getContext().setAuthentication(user);
        // 放行
        filterChain.doFilter(request,response);

    }
}
